package com.huaxin.common.tools;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;

import com.huaxin.common.BaseConfig;
import com.huaxin.common.Entity.UserInfoDTo;
import com.huaxin.common.RequestApi;
import com.huaxin.common.model.FileMsgResponseBean;
import com.huaxin.common.utils.HxCompressImageUtil;
import com.luck.picture.lib.config.PictureMimeType;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Cookie;
import okhttp3.CookieJar;
import okhttp3.HttpUrl;
import okhttp3.Interceptor;
import okhttp3.MediaType;
import okhttp3.MultipartBody;
import okhttp3.OkHttpClient;
import okhttp3.RequestBody;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Retrofit;
import retrofit2.adapter.rxjava.RxJavaCallAdapterFactory;
import retrofit2.converter.gson.GsonConverterFactory;
import retrofit2.converter.scalars.ScalarsConverterFactory;
import rx.Observable;
import rx.Subscriber;
import rx.android.schedulers.AndroidSchedulers;
import rx.schedulers.Schedulers;

/**
 * Created by Administrator on 2016/9/5.
 */
public class RequestHelper {
    private static Retrofit        retrofit;
    private static OkHttpClient    client;
    private static RequestApi      requestApi;
    private static ListenerHandler listenerHandler;
    private static Context         mContext;


    public static void clearCookie() {
        mCookies = null;
    }

    public static void clearRetrofit() {
        if (client != null && retrofit != null && requestApi != null) {
            client = null;
            retrofit = null;
            requestApi = null;
        }
    }

    private static List<Cookie> mCookies;

    public static void init(Context context) {
        mContext = context;
        if (listenerHandler == null) {
            listenerHandler = new ListenerHandler();
        }

        if (client == null) {
            CookieJar cookieJar = new CookieJar() {

                @Override
                public void saveFromResponse(HttpUrl url, List<Cookie> cookies) {
                    if (url.toString().contains("/app/login")) {
                        setCookies(cookies);
                        android.util.Log.d("123", "saveFromResponse:---1--> " + cookies);
                    }
                }

                @Override
                public List<Cookie> loadForRequest(HttpUrl url) {
                    if (url.toString().contains(BaseConfig.getUrl())) {
                        List<Cookie> cookies = getCookies();
                        return cookies != null ? cookies : new ArrayList<Cookie>();
                    }
                    return new ArrayList<Cookie>();
                }
            };

            HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
                @Override
                public void log(String message) {
                    //打印retrofit日志
                    Log.i("Request", message);
                }
            });
            loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);

            Interceptor downloadInterceptor = new Interceptor() {
                @Override
                public Response intercept(final Chain chain) throws IOException {
                    Response response = chain.proceed(chain.request());
                    //下载进度监听

                    return response.newBuilder()
                            .body(new ProgressResponseBody(response.body(), new ProgressListener() {
                                @Override
                                public void onProgress(long progress, long total, boolean done) {
                                    listenerHandler.obtainMessage(0, new MessageBean(chain
                                            .request().url(), progress, total, done))
                                            .sendToTarget();
                                }
                            }))
                            .build();
                }
            };

            client = new OkHttpClient.Builder()
                    .cookieJar(cookieJar)
                    //                    .addInterceptor(loggingInterceptor)  //与progressRequest冲突
                    .addNetworkInterceptor(downloadInterceptor)
                    .readTimeout(100, TimeUnit.SECONDS)//设置读取超时时间
                    .writeTimeout(100, TimeUnit.SECONDS)//设置写的超时时间
                    .connectTimeout(100, TimeUnit.SECONDS)//设置连接超时时间
                    .build();
        }
        if (retrofit == null) {
            retrofit = new Retrofit.Builder()
                    .baseUrl(BaseConfig.getUrl())
                    //增加返回值为String及基本数据类型的支持
                    .addConverterFactory(ScalarsConverterFactory.create())
                    //增加返回值为Gson的支持(以实体类返回)
                    .addConverterFactory(GsonConverterFactory.create())
                    //增加返回值为Oservable<T>的支持
                    .addCallAdapterFactory(RxJavaCallAdapterFactory.create())
                    .client(client)
                    .build();

        }
    }

    public static RequestApi getRequestApi() {
        if (requestApi == null) {
            requestApi = retrofit.create(RequestApi.class);
        }
        return requestApi;
    }

    /**
     * 这个方法是给BaseLibrary用的，本来BaseLibrary中有HxRetrofitClient
     * 但是后来架构调整，BaseLibrary不再作为基础库，而是大部分被Chat库使用
     * 所以创建此方法
     *
     * @return
     */
    public static Retrofit getRetrofit() {
        return retrofit;
    }

    public static List<Cookie> getCookies() {
        android.util.Log.d("11111", "getCookies: " + mCookies);
        return mCookies;
    }

    public static void setCookies(List<Cookie> mCookies) {
        RequestHelper.mCookies = mCookies;
    }


    //使用模板
    //单文件上传
    public static void singleFileUpload(Callback<String> callback, ProgressListener listener, File file) {
        //不带进度监听
        //      RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        //带进度监听，requestBody与listener一对一，不适用多文件上传
        ProgressRequestBody requestBody = new ProgressRequestBody(file, listener);
        //MultipartBody.Part 类型封装，有别于RequestBody类型
        MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        //        Call call = getMqttRequestApi().singleFileUpload(part);
        Call call = getRequestApi().singleFileUpload(BaseConfig.getMqttUrlPath(), part);
        call.enqueue(callback);
    }

    public static void uploadMsgFile2(Callback<FileMsgResponseBean> callback, ProgressListener listener, File file) {
        //不带进度监听
        //      RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        //带进度监听，requestBody与listener一对一，不适用多文件上传
        ProgressRequestBody requestBody = new ProgressRequestBody(file, listener);
        //MultipartBody.Part 类型封装，有别于RequestBody类型
        MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        //        Call call = getMqttRequestApi().singleFileUpload(part);
        Call call = getRequestApi().uploadMsgFile2(part);
        call.enqueue(callback);
    }

    //使用模板
    //单文件上传
    public static void uploadMsgFile(Callback<String> callback, ProgressListener listener, File file) {
        //不带进度监听
        //      RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        //带进度监听，requestBody与listener一对一，不适用多文件上传
        ProgressRequestBody requestBody = new ProgressRequestBody(file, listener);
        //MultipartBody.Part 类型封装，有别于RequestBody类型
        MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        //        Call call = getMqttRequestApi().singleFileUpload(part);
        Call call = getRequestApi().uploadMsgFile(part);
        call.enqueue(callback);
    }

    //文本、文件混合上传
    public static void mixUpload(Callback callback, ProgressListener listener, File file, String filename) {
        RequestBody requestBody = new ProgressRequestBody(file, listener);
        //RequestBody 类型封装，file部分报文中的文件名在接口声明中，不发动态修改，需另外添加filename参数，比较麻烦
        Call<String> call = getRequestApi().mixUpload(requestBody, filename);
        call.enqueue(callback);
    }

    //多文件上传
    public static void multiFileUpload(Callback<String> callback, File... files) {
        ArrayList<MultipartBody.Part> parts = new ArrayList<>();
        RequestBody requestBody;
        MultipartBody.Part part;
        for (File file : files) {
            requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
            part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
            parts.add(part);
        }
        Call call = getRequestApi().multiFileUpload(parts);
        call.enqueue(callback);
    }

    public static List<MultipartBody.Part> createFileParts(List<File> files) {
        ArrayList<MultipartBody.Part> parts = new ArrayList<>();
        for (File file : files) {
            RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
            MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
            parts.add(part);
        }
        return parts;
    }

    public static MultipartBody.Part createFilePart(File file) {
        RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), file);
        MultipartBody.Part part = MultipartBody.Part.createFormData("file", file.getName(), requestBody);
        return part;
    }

    public static List<MultipartBody.Part> submitFileParts(String[] paths) {
        ArrayList<MultipartBody.Part> parts = new ArrayList<>();

        for (int i = 0; i < paths.length; i++) {

            try {
                String cachePath = paths[i];
                //如果图片gif动态是不做压缩
                if (!PictureMimeType.isImageGif(paths[i])) {

                    cachePath = HxCompressImageUtil.compressImageBypixel(mContext, paths[i]);
                }
                File f = new File(cachePath);
                if (!f.exists()) {
                    continue;
                }
                RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), f);

                String fileType;
                Bitmap bitmap = BitmapFactory.decodeFile(cachePath);
                if (PictureMimeType.isImageGif(cachePath)) {
                    fileType = System.currentTimeMillis() + String.valueOf(i) + "_" + bitmap.getWidth() + "x" + bitmap.getHeight() + ".gif";
                } else {
                    fileType = System.currentTimeMillis() + String.valueOf(i) + "_" + bitmap.getWidth() + "x" + bitmap.getHeight() + ".png";
                }

                MultipartBody.Part part = MultipartBody.Part.createFormData("file", fileType, requestBody);
                parts.add(part);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return parts;
    }

    /**
     * 视频上传 目前需求单个上传
     * @param compressPaths
     * @return
     */
    public static List<MultipartBody.Part> createVideoParts(String[] compressPaths) {
        ArrayList<MultipartBody.Part> parts = new ArrayList<>();
        try {
            File f = new File(compressPaths[0]);
            RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), f);
            MultipartBody.Part part = MultipartBody.Part.createFormData("file", f.getName(), requestBody);
            parts.add(part);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return parts;
    }

    public static List<MultipartBody.Part> createFileParts(String[] paths) {
        ArrayList<MultipartBody.Part> parts = new ArrayList<>();
        for (String path : paths) {
            try {
                Log.i("lwjing","imagePath="+path);
                String cachePath = HxCompressImageUtil.compressImageBypixel(mContext, path);

                File f = new File(cachePath);
                //                Bitmap bitmap = getimage(path);
                //                try {
                //                    FileOutputStream fos = new FileOutputStream(f);
                //                    bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fos);
                //                    fos.flush();
                //                    fos.close();
                //                } catch (FileNotFoundException e) {
                //                    e.printStackTrace();
                //                } catch (IOException e) {
                //                    e.printStackTrace();
                //                }
                //
                if (!f.exists()) {
                    continue;
                }

                // String s = HxCompressImageUtil.compressImageBypixel(mContext, path);
                RequestBody requestBody = RequestBody.create(MediaType.parse("multipart/form-data"), f);
                MultipartBody.Part part = MultipartBody.Part.createFormData("file", f.getName(), requestBody);
                parts.add(part);
            } catch (Exception e) {
                e.printStackTrace();
            }

        }
        return parts;
    }

    /**
     * 图片按比例大小压缩方法
     *
     * @param srcPath （根据路径获取图片并压缩）
     * @return
     */
    public static Bitmap getimage(String srcPath) {
        BitmapFactory.Options newOpts = new BitmapFactory.Options();
        // 开始读入图片，此时把options.inJustDecodeBounds 设回true了
        newOpts.inJustDecodeBounds = true;
        Bitmap bitmap = BitmapFactory.decodeFile(srcPath, newOpts);// 此时返回bm为空

        newOpts.inJustDecodeBounds = false;
        int w = newOpts.outWidth;
        int h = newOpts.outHeight;
        // 现在主流手机比较多是800*480分辨率，所以高和宽我们设置为
        float hh = 800f;// 这里设置高度为800f
        float ww = 480f;// 这里设置宽度为480f
        // 缩放比。由于是固定比例缩放，只用高或者宽其中一个数据进行计算即可
        int be = 1;// be=1表示不缩放
        if (w > h && w > ww) {// 如果宽度大的话根据宽度固定大小缩放
            be = (int) (newOpts.outWidth / ww);
        } else if (w < h && h > hh) {// 如果高度高的话根据宽度固定大小缩放
            be = (int) (newOpts.outHeight / hh);
        }
        if (be <= 0)
            be = 1;
        newOpts.inSampleSize = be;// 设置缩放比例
        // 重新读入图片，注意此时已经把options.inJustDecodeBounds 设回false了
        bitmap = BitmapFactory.decodeFile(srcPath, newOpts);
        return compressImage(bitmap);// 压缩好比例大小后再进行质量压缩
    }

    /**
     * 质量压缩方法
     *
     * @param image
     * @return
     */
    public static Bitmap compressImage(Bitmap image) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        image.compress(Bitmap.CompressFormat.JPEG, 100, baos);// 质量压缩方法，这里100表示不压缩，把压缩后的数据存放到baos中
        int options = 90;
        while (baos.toByteArray().length / 1024 > 100) { // 循环判断如果压缩后图片是否大于100kb,大于继续压缩
            baos.reset(); // 重置baos即清空baos
            options -= 10;// 每次都减少10
            image.compress(Bitmap.CompressFormat.JPEG, options, baos);// 这里压缩options%，把压缩后的数据存放到baos中
        }
        ByteArrayInputStream isBm = new ByteArrayInputStream(baos.toByteArray());// 把压缩后的数据baos存放到ByteArrayInputStream中
        Bitmap bitmap = BitmapFactory.decodeStream(isBm, null, null);// 把ByteArrayInputStream数据生成图片

        return bitmap;
    }


    //静态方法，便于作为工具类
    private static String getMd5(String plainText) {
        try {
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(plainText.getBytes());
            byte b[] = md.digest();
            int i;
            StringBuffer buf = new StringBuffer("");
            for (int offset = 0; offset < b.length; offset++) {
                i = b[offset];
                if (i < 0)
                    i += 256;
                if (i < 16)
                    buf.append("0");
                buf.append(Integer.toHexString(i));
            }
            //32位加密
            return buf.toString();
            // 16位的加密
            //return buf.toString().substring(8, 24);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
            return "" + System.currentTimeMillis() + ".png";
        }
    }


    public static void addDownloadListener(HttpUrl call, ProgressListener progressListener) {
        listenerHandler.addListener(call, progressListener);
    }

    public static void reconnectListener(HttpUrl call, ProgressListener progressListener) {
        listenerHandler.reconnectListener(call, progressListener);
    }


    public static class MessageBean {
        private HttpUrl mRequest;
        private long    mProgress;
        private long    mTotal;
        private boolean mDone;

        public MessageBean(HttpUrl request, long progress, long total, boolean done) {
            mRequest = request;
            mProgress = progress;
            mTotal = total;
            mDone = done;
        }

        public HttpUrl getRequest() {
            return mRequest;
        }

        public long getProgress() {
            return mProgress;
        }

        public long getTotal() {
            return mTotal;
        }

        public boolean isDone() {
            return mDone;
        }
    }

    public static class ListenerHandler extends Handler {

        private Map<HttpUrl, ProgressListener> listenerMap = new HashMap<>();

        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            MessageBean mBean = (MessageBean) msg.obj;
            ProgressListener pListener = listenerMap.get(mBean.getRequest());
            if (pListener != null) {
                pListener.onProgress(mBean.getProgress(), mBean.getTotal(), mBean.isDone());
                if (mBean.isDone()) {
                    listenerMap.remove(mBean.getRequest());
                }
            }

        }

        public void addListener(HttpUrl call, ProgressListener progressListener) {
            listenerMap.put(call, progressListener);
        }

        public void reconnectListener(HttpUrl call, ProgressListener progressListener) {
            if (listenerMap.containsKey(call)) {
                listenerMap.put(call, progressListener);
            }
        }

    }

    //增加返回值为Oservable<T>的支持
    public static void testOservable() {
        Observable<UserInfoDTo> observable = getRequestApi().testOservable();
        observable.subscribeOn(Schedulers.io())
                .unsubscribeOn(Schedulers.io())
                .observeOn(AndroidSchedulers.mainThread())
                .subscribe(new Subscriber<UserInfoDTo>() {
                    @Override
                    public void onCompleted() {
                        Log.d("Zoes", "complete:" + Thread.currentThread().getId());
                    }

                    @Override
                    public void onError(Throwable e) {
                        Log.d("Zoes", "error:" + Thread.currentThread().getId());
                    }

                    @Override
                    public void onNext(UserInfoDTo userInfoEntity) {
                        Log.d("Zoes", "next:" + Thread.currentThread().getId());
                    }
                });
    }
}
